import {
  ExecutionContext,
  ForbiddenException,
  Injectable,
  UnauthorizedException,
} from '@nestjs/common'
import { Reflector } from '@nestjs/core'
import { JsonWebTokenError, TokenExpiredError } from '@nestjs/jwt'
import { AuthGuard } from '@nestjs/passport'
import { Observable } from 'rxjs'
import { IS_PUBLIC_KEY } from '@/decorators/public.decorator'

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  constructor(private reflect: Reflector) {
    super()
  }

  canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
    const isPublic = this.reflect.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
      context.getHandler(),
      context.getClass(),
    ])
    if (isPublic) {
      return true
    }
    return super.canActivate(context)
  }
  // 在大多数情况下，使用一个提供的AuthGuard类是有用的。然而，在一些用例中你可能只是希望简单地扩展默认的错误处理或者认证逻辑。在这种情况下，你可以通过一个子类来扩展内置的类并且覆盖其方法。
  // 覆盖AuthGuard类中的错误处理方法， 定义自己的错误处理方法
  handleRequest(err: any, user: any, info: any) {
    // 可以抛出一个基于info或者err参数的异常
    if (err || !user) {
      if (info instanceof TokenExpiredError) {
        throw err || new UnauthorizedException('token过期，请刷新token')
      } else if (info instanceof JsonWebTokenError) {
        throw err || new ForbiddenException('用户授权信息错误')
      } else {
        throw err || new ForbiddenException('用户未授权')
      }
    }
    return user
  }
}
